import {forEach,getFormatDate} from './../plugins/tools.js'
import Participant from './participant.js'

class Room {

    //开会中成员(名称)
    meeting = []
    //固定成员
    fixed = {}
    //临时成员
    temp = {}
    //邀请成员(名称)
    invite = []

    name = ''
    no = ''
    number = null
    route = null
    host = null
    intercom = null
    isVideo = false
    record = false
    forceRecord = false
    isTemp = false
    deptId = null
    mute = false
    isMeeting = false

    meetingInfos = []

    confApi = null

    constructor(name, no, number, route, host, intercom, isVideo, record, deptId, isTemp, confApi) {
        this.name = name
        this.no = no
        this.number = number
        this.route = route
        this.host = host
        this.intercom = intercom
        this.isVideo = isVideo
        this.record = record
        this.deptId = deptId

        this.isTemp = isTemp
        if (isTemp === undefined || isTemp === null) {
            this.isTemp = name.indexOf('-@-') > -1
        } else {
            this.isTemp = isTemp
        }
        if (this.isTemp) {
            this.no = this.name
        }
        this.meetingInfos = []
        this.confApi = confApi
    }

    asyncInfo(name, type) {
        let json ={time:getFormatDate('HH:MM:SS',new Date()),name,room:this.name, type}
        this.meetingInfos.unshift(json)
    }

    info(key, value, appKey, type) {
        if (!key) {
            key = 'name'
        }
        let pt = null
        let isTemp = false
        for (const key in this.temp) {
            let participant = this.temp[key]
            if (participant[key] === value) {
                isTemp = participant.isTemp
                if (appKey) {
                    if (participant.gradeNumber === appKey) {
                        pt = participant
                        break
                    }
                }else {
                    pt = participant
                    break
                }
            }
        }
        if (!isTemp) {
            for (const key in this.fixed) {
                let participant = this.fixed[key]
                if (participant[key] === value) {
                    isTemp = participant.isTemp
                    if (appKey) {
                        if (participant.gradeNumber === appKey) {
                            pt = participant
                            break
                        }
                    } else {
                        pt = participant
                        break
                    }
                }
            }
        }

        let json = {}
        if (!pt) {
            json.name = value
        } else {
            json.name = pt.name
        }
        json.time = getFormatDate('HH:MM:SS', new Date())
        json.room = this.name
        json.type = type

        this.meetingInfos.unshift(json)

    }

    addParticipant(participant, inRoom) {
        return new Promise((resolve, reject) => {
            let key = participant.name
            if (participant.type === 1 && participant.number) {
                key = participant.number
            }
            if (participant.isTemp) {
                let _participant = this.temp[key]
                if (_participant) {
                    participant.rtcPeer = _participant.rtcPeer
                    participant.speakHark = _participant.speakHark
                }
                this.temp[key] = participant
            } else {
                let _participant = this.fixed[key]
                if (_participant) {
                    participant.rtcPeer = _participant.rtcPeer
                    participant.speakHark = _participant.speakHark
                    if (_participant.status === 'Talking') {
                        participant.setStatus(_participant.status)
                    }
                }

                let __participant = this.temp[key]
                if (__participant) {
                    delete this.temp[key]
                }
                this.fixed[key] = participant
            }
            if (inRoom && (participant.status === 'Talking' || participant.status === 'Ringing')) {
                this.isMeeting = true
                if (participant.status === 'Talking') {
                    if (this.meeting.indexOf(participant.name) < 0) {
                        this.meeting.push(participant.name)
                    }
                    this.removeInviteParticipant('name', participant.name)
                }
                resolve(this, this.meeting, participant)
            }
        })

    }

    removeParticipant(key, value, appKey) {
        return new Promise((resolve, reject) => {
            if (!key) {
                key = 'name'
            }
            let participant = null
            for (const pk in this.temp) {
                let _participant = this.temp[pk]
                if (_participant[key] === value) {
                    if (appKey) {
                        if (_participant.gradeNumber === appKey) {
                            participant = _participant
                            break
                        }
                    }else {
                        participant = _participant
                        break
                    }
                }
            }
            if (!participant) {
                for (const pk in this.fixed) {
                    let _participant = this.fixed[pk]
                    if (_participant[key] === value) {
                        if (appKey) {
                            if (_participant.gradeNumber === appKey) {
                                participant = _participant
                                break
                            }
                        }else {
                            participant = _participant
                            break
                        }
                    }
                }
            }
            if (!participant) {
                reject('no match participant!')
                return console.error('no match participant!')
            }
            if (participant.isTemp) {
                delete this.temp[participant.name]
            } else {
                let json = {name: participant.name, type: participant.type, canInvite: true, number: participant.number}
                this.invite.unshift(json)
            }
            if (this.meeting.indexOf(participant.name) > -1) {
                this.meeting.splice(this.meeting.indexOf(participant.name), 1)
                resolve(this, this.meeting, participant)
            }
            if (this.meeting.length <= 0) {
                this.dispose()
            }
        })

    }

    changeVcsParticipant(data) {
        return new Promise((resolve, reject) => {
            if (!data) {
                reject('data error')
                return console.error('data error!')
            }
            let participant = this.fixed[data.name]
            if (!participant) {
                participant = this.temp[data.name]
            }
            if (participant) {
                participant.muted = data.mute
                participant.muteVideo = data.muteVideo
                participant.setStatus('Talking')
                this.isMeeting = true
                if (participant.type == 4 || participant.type == 5) {
                    participant.muted = true
                    data.mute = true
                }
                if (participant.muted) {
                    participant.meetingIcon = 'conf_mute'
                } else {
                    participant.meetingIcon = 'conf'
                }
                if (this.meeting.indexOf(participant.name) < 0) {
                    this.meeting.push(participant.name)
                    resolve(this, participant)
                }
                this.removeInviteParticipant('name', participant.name)
            } else {
                let _participants = []
                let type = data.type
                if (type == 'SIP话机') {
                    type = 'sip'
                }else if (type == '摄像头') {
                    type = 'camera'
                    data.mute = true
                }
                let _participant = {name:data.name,type:type,mute:data.mute, muteVideo: data.muteVideo}
                _participants.push(_participant)
                this.confApi.queryVcsConferenceMembers(_participants).then(result=>{
                    if (result.code === 200) {
                        let _data = result.data
                        let _arr = []
                        forEach(_data,d=>{
                            let name = d.name
                            if (d.channel) {
                                name = d.name + '_' + d.channel
                                this.removeInviteParticipant('name', d.name)
                            }
                            let __participant = new Participant(name, this.name, d.exten, d.type, d.vcs, d.gradeNum, false)
                            if (d.channel) {
                                __participant.realName = d.name
                            }
                            __participant.isTemp = d.temp
                            __participant.muteVideo = data.muteVideo
                            if (d.inRoom) {
                                if (d.mute) {
                                    __participant.muted = true
                                    __participant.meetingIcon = 'conf_mute'
                                } else {
                                    __participant.muted = false
                                    __participant.meetingIcon = 'conf'
                                }
                            }else{
                                __participant.meetingIcon = ''
                            }
                            if (d.status === 'UnKnown') {
                                d.status = 'UnKnow'
                            }
                            __participant.setStatus(d.status)
                            __participant.setDept(d.deptId, d.deptName)
                            __participant.icon = ''
                            __participant.net = d.net
                            __participant.gradeName = d.gradeName
                            this.addParticipant(__participant,d.inRoom)
                            _arr.push(__participant)
                        })

                        if (this.meeting.indexOf(data.name) < 0) {
                            this.meeting.push(data.name)
                            resolve(this, this.meeting, _arr)
                        }
                        this.removeInviteParticipant('name', data.name)
                    }
                })
            }
        })
    }

    vcsLeave(json) {
        return new Promise((resolve, reject) => {
            let isTemp = false
            let participant = this.fixed[json.name]
            if (!participant) {
                participant = this.temp[json.name]
                if (participant) {
                    isTemp = true
                    delete this.temp[json.name]
                }
            }
            if (participant) {
                participant.dispose()
                if (participant.status === 'Talking') {
                    participant.setStatus('Idle')
                }
                if (participant.type == 4 && participant.isRtsp) {
                    participant.setStatus('UnKnow')
                }
                participant.meetingIcon = ''
            }
            if (this.meeting.indexOf(json.name) > -1) {
                this.meeting.splice(this.meeting.indexOf(json.name), 1)
            }
            resolve(this, this.meeting, participant)
            if (isTemp) {
                return
            }
            if (participant.isControl) {
                if (this.meeting.length > 0) {
                    for (const key in this.fixed) {
                        this.fixed[key].dispose()
                    }
                    for (const key in this.temp) {
                        this.temp[key].dispose()
                    }
                }

            }

            let info = {name:participant.name,type:participant.type,canInvite:true, number: participant.number}
            this.invite.unshift(info)
            if (this.isTemp) {
                if (Object.keys(this.temp).length <= 0) {
                    //todo close room
                    this.dispose()
                }
            }
        })
    }

    vcsCandidate(json, number) {
        let participant = this.fixed[json.name]
        if (!participant) {
            participant = this.temp[json.name]
        }
        if (!participant.rtcPeer) {
            if (number == 1) {
                return
            }
            setTimeout(() => {
                this.vcsCandidate(json, 1)
            }, 500)
        }
        if (!participant.rtcPeer) {
            return console.error('participant :%s no rtcpeer!', participant.name)
        }
        participant.rtcPeer.addIceCandidate(json.candidate,function (error) {
            if (error) return console.error('Error adding candidate:', error)
        })

    }

    vcsAnswer(json) {
        let participant = this.fixed[json.name]
        if (!participant) {
            participant = this.temp[json.name]
        }
        if (!participant.rtcPeer) {
            return console.error('participant : %s answer error!', participant.name)
        }
        participant.rtcPeer.processAnswer(json.sdpAnswer, function (error) {
            if (error) return console.error('Participant answer error:',error)
        })
    }

    addVcsParticipant(data) {
        return new Promise((resolve, reject) => {
            if (!data || data.length <= 0) {
                reject('no data!')
                return
            }
            let add = []
            if (data.roomName === this.name) {
                if (!this.forceRecord) {
                    this.record = data.record
                }
                let participants = data.participantNames
                if (participants && participants.length > 0) {
                    for (let i = 0; i < participants.length; i++) {
                        let name = participants[i].name
                        if (this.meeting.indexOf(name) < 0) {
                            this.meeting.push(name)
                            this.changeVcsParticipant(participants[i])
                            add.push(name)
                        }
                    }
                }
            }
            resolve(this,add)
        })
    }

    changeInvite(key, appKey, value) {
        return new Promise((resolve, reject) => {
            if (!this.isMeeting) {
                reject('meeting not start!')
                return console.info('会议未开始!')
            }
            if (!key) {
                key = 'name'
            }
            let reInvite = null
            for (let i = 0; i < this.invite.length; i++) {
                let participant = this.invite[i]
                if (participant[key] === value) {
                    if (appKey) {
                        if (appKey === participant.gradeNumber) {
                            reInvite = participant
                            break
                        }
                    } else {
                        reInvite = participant
                        break
                    }
                }
            }
            resolve(this.name, reInvite)
        })
    }

    clearParticipant() {
        if (this.isVideo) {
            if (!this.isMeeting) {
                this.fixed = {}
                this.temp = {}
                this.meeting = []
            }
        }else {
            this.fixed = {}
            this.temp = {}
            this.meeting = []
            this.isMeeting = false
        }
    }

    getParticipants() {
        let participants = []
        let gbNames = new Set()
        for (const key in this.temp) {
            let _participant = this.temp[key]
            if (_participant.realName !== _participant.name) {
                gbNames.add(_participant.realName)
            }
            participants.push(this.temp[key])
        }
        let _gbNames = Array.from(gbNames)
        for (const key in this.fixed) {
            let _participant = this.fixed[key]
            if (_gbNames.length > 0) {
                if ((_participant.type == 4 || _participant.type == 5) && _gbNames.indexOf(_participant.name) > -1) {
                    continue
                }
            }
            participants.unshift(this.fixed[key])
        }
        return participants
    }

    getParticipant(name, type) {
        let participant1 = this.fixed[name]
        let participant2 = this.temp[name]
        if (type == 'temp') {
            return participant2
        }else if (type == 'fix') {
            return participant1
        } else {
            return participant1 ? participant1 : participant2
        }
    }

    getParticipantByNumber(number, appKey) {
        if (!number) {
            return null
        }
        for (const key in this.fixed) {
            let _participant = this.fixed[key]
            if (appKey) {
                if (appKey === _participant.gradeNumber && _participant.number === number) {
                    return _participant
                }
            }else {
                if (_participant.number === number) {
                    return _participant
                }
            }
        }
        for (const key in this.temp) {
            let _participant = this.temp[key]
            if (appKey) {
                if (appKey === _participant.gradeNumber && _participant.number === number) {
                    return _participant
                }
            }else {
                if (_participant.number === number) {
                    return _participant
                }
            }
        }
        return null
    }

    reloadRoom(number, appKey) {
        return new Promise((resolve, reject) => {
            for (const key in this.fixed) {
                let _participant = this.fixed[key]
                if (_participant.number === number) {
                    if (appKey) {
                        if (appKey === _participant.gradeNumber) {
                            resolve(this, _participant)
                            return
                        }
                    } else {
                        resolve(this, _participant)
                        return
                    }
                }
            }
            for (const key in this.temp) {
                let _participant = this.temp[key]
                if (_participant.number === number) {
                    if (appKey) {
                        if (appKey === _participant.gradeNumber) {
                            resolve(this, _participant)
                            return
                        }
                    } else {
                        resolve(this, _participant)
                        return
                    }
                }
            }
            resolve(this, null)
        })
    }

    clearInvite() {
        if (!this.isMeeting) {
            this.invite = []
        }
    }

    addInviteParticipant(data) {
        if (this.invite.length <= 0) {
            this.invite.push(data)
            return
        }
        let exists = this.invite.filter(p => p.name === data.name)
        if (exists && exists.length > 0 || this.meeting.indexOf(data.name) > 0) {
            return
        }
        this.invite.push(data)
    }

    removeInviteParticipant(key, value, appKey) {
        if (this.invite.length <= 0) {
            return
        }
        if (!key) {
            key = 'name'
        }
        let index = -1
        let toInvite = null
        for (let i = 0; i < this.invite.length; i++) {
            let ring = this.invite[i]
            if (ring[key] === value) {
                if (appKey) {
                    if (ring.gradeNumber === appKey) {
                        index = i
                        toInvite = ring
                    }
                }else {
                    index = i
                    toInvite = ring
                }
            }
        }
        if (index > -1) {
            this.invite.splice(index, 1)
        }
        return toInvite
    }

    meetings(status) {
        let _participants = []
        if (this.meeting.length <= 0) {
            return _participants
        }
        for (let i = 0; i < this.meeting.length; i++) {
            let participant = null
            let pm = this.meeting[i]
            for (const key in this.fixed) {
                let fixedParticipant = this.fixed[key]
                if (fixedParticipant.name === pm) {
                    participant = fixedParticipant
                    break
                }
            }
            if (!participant) {
                for (const key in this.temp) {
                    let tempParticipant = this.temp[key]
                    if (tempParticipant.name === pm) {
                        participant = tempParticipant
                        break
                    }
                }
            }
            if (participant) {
                if (status) {
                    if (participant.status === status) {
                        _participants.push(participant)
                    }
                }else {
                    _participants.push(participant)
                }
            }
        }
        return _participants
    }

    muteAll() {
        if (this.isVideo) {
            for (const key in this.fixed) {
                this.fixed[key].setMute(true)
                this.asyncInfo(this.fixed[key].name, 'mute')
            }
            for (const key in this.temp) {
                this.temp[key].setMute(true)
                this.asyncInfo(this.temp[key].name, 'mute')
            }
        }
        this.mute = true
    }

    unMuteAll() {
        if (this.isVideo) {
            for (const key in this.fixed) {
                this.fixed[key].setMute(false)
                this.asyncInfo(this.fixed[key].name, 'unMute')
            }
            for (const key in this.temp) {
                this.temp[key].setMute(false)
                this.asyncInfo(this.temp[key].name, 'unMute')
            }
        }
        this.mute = false
    }

    setForceRecord(force) {
        this.forceRecord = force
    }

    inRoom(name) {
        return this.meeting.indexOf(name) > -1
    }

    dispose() {
        return new Promise((resolve, reject)=>{
            if (this.isVideo) {
                for (const key in this.temp) {
                    let participant = this.temp[key]
                    participant.dispose()
                }
                for (const key in this.fixed) {
                    let participant = this.fixed[key]
                    participant.dispose()
                }
            }

            this.isMeeting = false
            this.record = this.forceRecord
            this.meeting = []
            this.invite = []
            this.temp = {}

            resolve(this)
        })
    }
}

export default Room